package net.zoneland.knowledge.service.impl.search;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import net.zoneland.knowledge.config.EsConfig;
import net.zoneland.knowledge.config.SearchStrategyConfig;
import net.zoneland.knowledge.constant.SystemConstant;
import net.zoneland.knowledge.constant.FieldConstant;
import net.zoneland.knowledge.enums.DictParentEnum;
import net.zoneland.knowledge.model.DictItem;
import net.zoneland.knowledge.model.EsQuestion;
import net.zoneland.knowledge.service.DictItemService;
import net.zoneland.knowledge.service.EsService;
import net.zoneland.knowledge.utils.ElasticSearchPoolUtil;
import net.zoneland.knowledge.utils.EsQueryUtils;
import net.zoneland.knowledge.utils.ResponseUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 固定词组.
 *
 * @author: bcc
 * 2021/5/26
 */
@Service("searchOperationImplQueryFixWords")
public class SearchOperationImplQueryFixWords extends AbstractSearchOperation {

    /**
     * logger.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(SearchOperationImplQueryFixWords.class);

    /**
     * guava缓存，获取内存
     */
    private static final Cache<String, List<String>> cache = CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).build();

    /**
     * 固定词组缓存key.
     */
    private static final String FIX_WORD_KEY = "fixWordKey";

    @Autowired
    private DictItemService dictItemService;

    @Autowired
    private EsService esService;
    
    @Autowired
    private SearchStrategyConfig searchStrategyConfig;


    @Override
    public boolean needRun(final SearchDto searchDto) {
        try {
            List<String> fixWords  =  getFixWordsList();
            final boolean configFixWord = CollectionUtils.isNotEmpty(fixWords)
                    && fixWords.contains(searchDto.getQaQueryDto().getQueryText());
            if (configFixWord || searchStrategyConfig.isFixWord()) {
               return !searchDto.isStopSearch();
            }
        } catch (ExecutionException e) {
            LOGGER.error("查询fixWord出错", e);
        }
        return false;
    }

    /**
     * 获取固定词.
     *
     * @return 关键字列表
     */
    private List<String> getFixWordsList() throws ExecutionException {
        List<String> list = cache.get(FIX_WORD_KEY, () -> {
            List<DictItem> dicts = dictItemService.findDictByParentId(DictParentEnum.SEARCH_FIX_KEYWORD.getValue());
            if (CollectionUtils.isNotEmpty(dicts)) {
                return dicts.stream().map(DictItem::getDictValue).collect(Collectors.toList());
            }
            //  guava 设置expireAfterWrite后返回null会报错
            return new ArrayList<>();
        });
        return list;
    }

    @Override
    protected void doSearchOrDeal(final SearchDto searchDto) throws Exception {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("start queryFixWord {}", searchDto);
        }
        try {
            final List<EsQuestion> result = esService.queryByFixWordKey(searchDto.getQaQueryDto());
            if (CollectionUtils.isNotEmpty(result)) {
                searchDto.setEsQuestions(result);
                if (searchStrategyConfig.isFixWordStop()) {
                   searchDto.setStopSearch(true); 
                }
            }
        } catch (Exception e) {
            searchDto.setErrorFlag(true);
            LOGGER.error("SearchOperationImplQueryFixWords error", e);
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("end queryFixWord {}", searchDto);
        }
    }

}
